home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
DDJ0192.ARJ
/
DISKDUP.ASC
< prev
next >
Wrap
Text File
|
1991-11-21
|
21KB
|
868 lines
_YOUR OWN DISK DUPLICATOR PROGRAM_
by Al Williams
[LISTING ONE]
/****************************************************************
* CB386.H - include file for CopyBuilder 386 *
* See makefile for compile directives -- Al Williams *
****************************************************************/
#define NRTRIES 3 /* number of times to retry disk ops */
/* force codebuilder to not align */
#pragma align(_bpb=1)
/* structre of disk BPB */
extern struct _bpb
{
unsigned char jump[3];
char oemname[8];
unsigned short bytespersec;
unsigned char secperclust;
unsigned short ressectors;
unsigned char nrfats;
unsigned short rootsize;
unsigned short nrsectors;
char media;
unsigned short fatsectors;
unsigned short secpertrack;
unsigned short nrheads;
unsigned int hiddensecs;
unsigned int hugesectors;
unsigned char physdrive;
char notused;
unsigned char signature; /* should be 0x29 */
unsigned int serno;
char label[11];
char type[8];
char pad[512-60]; /* rest of 512 byte sector */
} bpb;
/* various globals */
extern int driveno;
extern unsigned disksize;
extern unsigned sectorct;
/* disk image buffer */
extern unsigned char *diskbuf;
/* DOS buffer used to communicate with BIOS */
extern char *dosbuf;
/* set by critical errors */
extern int critical_err;
/* information on buffer */
extern struct _bufinfo
{
char title[65];
unsigned size;
unsigned short copies;
char source[13];
/* checksums (stored and computed) */
unsigned short csum, ccsum;
short dirty;
} bufinfo;
extern void (*slbreak)(); /* place to hook break handler */
/* holds disk format command */
extern char fmtcmd[];
/* additional break handler */
extern void (*when_break)();
/* prototypes for break handlers */
void load_break();
void save_break();
/* general prototypes */
int sector_read(int head, int track, int sector, int drive,
unsigned char *buf,unsigned count);
int sector_write(int head, int track, int sector, int drive,
unsigned char *buf,unsigned count);
/* disable reboot */
void noreboot(void);
void okreboot(void);
[LISTING TWO]
/****************************************************************
* CB386.C - main file for CopyBuilder 386 *
* See makefile for compile directives -- Al Williams *
****************************************************************/
#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include "cb386.h"
#include "display.h"
/* current drive number */
int driveno;
/* current bios parameter block */
struct _bpb bpb;
/* size of disk */
unsigned disksize;
/* information about buffer */
struct _bufinfo bufinfo;
/* number of sectors */
unsigned sectorct;
/* storage for disk image */
unsigned char *diskbuf;
/* set when a critical error occurs */
int critical_err;
/* DOS buffer for disk BIOS reads and writes */
char *dosbuf;
/* text of format command */
char fmtcmd[129];
/* set when a critical error occurs */
int critical_err;
/* critical error messages */
static char *cmsgs[]=
{
"Write protect",
"Unknown unit",
"Drive not ready",
"Unknown command",
"CRC error",
"Bad Request",
"Seek error",
"Unknown media",
"Sector not found",
"Out of paper",
"Write error",
"Read error",
"General failure",
"Unknown",
"Unknown",
"Invalid change"
};
/* Critical error handler */
void cerror(int dev,int code)
{
char msg[81];
int choice;
critical_err=code&=0xFF;
sprintf(msg,"Critical error: %s (Retry, Fail, Ignore)", cmsgs[code]);
choice=prompt(msg,"RIF",ERRCOLOR);
if (choice==0) choice=_HARDERR_RETRY;
else if (choice==1) choice=_HARDERR_IGNORE;
else choice=_HARDERR_FAIL; /* F or ESC */
_hardresume(choice);
}
/* main program */
main(int argc,char *argv[])
{
/* set up critical error handler */
_harderr(cerror);
if (argc>2||argv[1][0]=='?'||argv[1][1]=='?')
error("CopyBuilder 386 by Al Williams\n"
"A diskette duplication system\n"
"Usage: CB386 [drive]\n");
/* save current drive/directory */
cdsave();
/* set up video mode and detect monitor type */
vidmode();
/* if mono monitor, set up neutral colors */
if (mono)
{
TEXTCOLOR=7;
SOCOLOR=0x70;
ERRCOLOR=1;
HELPCOLOR=7;
}
/* reset title, etc. */
strcpy(bufinfo.title,"<EMPTY>");
strcpy(bufinfo.source,"N/A");
strcpy(fmtcmd,"format");
noreboot();
/* if user asked for a disk on the command line, read it */
if (argc==2)
{
/* show a display */
disp();
/* read the disk */
read_disk(*argv[1]);
}
/* goto main menu */
menu();
}
/* Non-interactive error routine */
error(char *s)
{
printf("\n%s\n",s);
cdrestore();
exit(1);
}
/* compute checksum
add sixteen bit words and wrap carry around */
checksum()
{
unsigned char *bufp=diskbuf;
int i=bufinfo.size;
unsigned short cksum=0;
unsigned cksum1;
while (i--)
{
cksum1=cksum;
cksum1+=*bufp++;
cksum=cksum1&0xFFFF;
if (cksum1&0xFFFF0000)
cksum++;
}
bufinfo.ccsum=cksum;
return cksum;
}
/* Format a disk in the indicated drive */
format(int driveno)
{
char fcmd[80];
int stat;
/* build command line */
sprintf(fcmd,"%s %c:",fmtcmd,driveno+'A');
/* save video */
vidsave();
/* execute command */
stat=system(fcmd);
vidrestore();
if (stat==-1) advise("Unable to execute format program");
}
/* turn the blinking -wait- on at bottom of screen */
wait_on()
{
int ocolor=color;
color=SOCOLOR|0x80; /* make it blink */
goxy(0,24);
clreol();
goxy(37,24);
printfc("-WAIT-");
curshide();
color=ocolor;
}
/* turn the blinking -wait- off at bottom of screen */
wait_off()
{
goxy(0,24);
clreol();
}
[LISTING THREE]
/****************************************************************
* FILEIO.C File oriented I/O routines for CB386 *
* See makefile for compile directives -- Al Williams *
****************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include "cb386.h"
#include "display.h"
void (*slbreak)(); /* place to hook break handler */
/* ^C handler when saving -- used in DISKIO.C too */
void save_break()
{
advise("\aOperation aborted");
if (slbreak) slbreak();
when_break=slbreak;
}
/* ^C handler when loading -- used in DISKIO.C too */
void load_break()
{
cleanup();
when_break=slbreak;
}
/* Clean up an aborted load */
cleanup()
{
if (diskbuf) free(diskbuf);
diskbuf=NULL;
memset(&bufinfo,0,sizeof(bufinfo));
strcpy(bufinfo.title,"<EMPTY>");
strcpy(bufinfo.source,"N/A");
}
/* save disk image to a file */
m_save()
{
slbreak=when_break;
when_break=save_break;
saveit();
when_break=slbreak;
slbreak=NULL;
}
/* load disk image to a file */
m_load()
{
slbreak=when_break;
when_break=load_break;
loadit();
when_break=slbreak;
slbreak=NULL;
}
/* actual routine to save data */
saveit()
{
char fn[66];
FILE *f=NULL;
int cnt1;
/* if no data to save, forget it */
if (!diskbuf)
{
advise("No disk image in memory");
return;
}
/* get a file name */
if (!getfilen(fn,65)) return;
critical_err=0;
/* check if the file already exists */
if (!access(fn,0))
{
if (prompt("\aFile exists. Overwrite? (Y/N)"
,"NY",TEXTCOLOR)<=0)
return;
}
/* if checking for the file caused a critical error,
don't even try to open the file */
if (!critical_err) f=fopen(fn,"wb");
/* if the file can't be opened (or wasn't because of
a critical error, forget it */
if (!f)
{
advise("Can't open file for writing");
return;
}
/* Get a title */
if (ask("Title: ",NULL,TEXTCOLOR,64,fn,NULL)==-1) return;
/* only change title if new one was entered */
if (*fn) strcpy(bufinfo.title,fn);
/* Turn the wait indicator on */
wait_on();
/* set dirty bit in image. copies/source/csum are meaningless */
bufinfo.dirty=1;
/* write signature */
putw('C386',f);
/* write size of bufinfo */
putw(sizeof(struct _bufinfo),f);
/* write bufinfo */
fwrite(&bufinfo,1,sizeof(struct _bufinfo),f);
/* write entire buffer in one swoop */
cnt1=fwrite(diskbuf,1,bufinfo.size,f);
/* one | is deliberate here -- we always want to fclose */
if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
advise("\aError writing to file");
else
bufinfo.dirty=0;
wait_off();
}
/* routine to actually load file to disk image */
loadit()
{
char fn[66];
FILE *f;
int cnt,cnt1;
/* if buffer is full, confirm */
if (!dirtyquery()) return;
/* get file name */
if (!getfilen(fn,65)) return;
/* open it */
f=fopen(fn,"rb");
/* can't open it, forget it */
if (!f)
{
advise("Can't open file");
return;
}
/* Turn wait indicator on */
wait_on();
/* check file type */
cnt=getw(f);
if (cnt!='C386')
{
advise("Not a C386 image file");
return;
}
/* get size of bufinfo structure */
cnt=getw(f);
/* new versions of C386 can't make bufinfo smaller, only larger
at the end */
fread(&bufinfo,1,cnt,f);
/* kill old image */
if (diskbuf) free(diskbuf);
/* allocate new image based on size */
diskbuf=malloc(bufinfo.size);
if (!diskbuf)
{
advise("Insufficient memory");
cleanup();
fclose(f);
return;
}
/* read it all in */
cnt1=fread(diskbuf,1,bufinfo.size,f);
/* one | is deliberate here also (see saveit(), above) */
if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
{
advise("Error reading file");
cleanup();
return;
}
checksum();
strcpy(bufinfo.source,fn);
bufinfo.copies=0;
wait_off();
}
[LISTING FOUR]
/****************************************************************
* REBOOT.C - Disable ^ALT-DEL for CodeBuilder programs *
* Al Williams -- August 1991 *
****************************************************************/
#include <stdio.h>
#include <i32.h>
#include <stk.h>
#include <dos.h>
#include <conio.h>
/* When running DOS we replace the keyboard interrupt
(INT 9) */
/* old INT 9 handler */
static void (*oldint9)();
#pragma interrupt(ourint9)
/* replacement interrupt handler */
static void ourint9()
{
int code,temp;
/* pointer to CodeBuilder stack frames */
_XSTACK *frame=_get_stk_frame();
/* pointer to BIOS shift status byte */
unsigned char *shift_status=(unsigned char *)0x417;
/* read keyboard */
code=inp(0x60);
/* DEL is scan code 0x53 -- if *shift_status&0xc==0xc then shift
and Alt are down */
if (code!=0x53||(*shift_status&0xc)!=0xc) _chain_intr(oldint9);
/* will not allow ^ALT-DEL */
/* consume key from keyboard */
temp=inp(0x61);
outp(0x61,temp|0x80);
outp(0x61,temp);
outp(0x20,0x20);
/* Tell CodeBuilder not to reissue interrupt */
frame->opts=_STK_NOINT;
return;
}
/* This function locks the page ourint9 is on so it can't be swapped out.
4K is the minimum size, and surely ourint9 isn't that big.... */
static lockint9(int flag)
{
static lock=0;
if (flag!=lock)
{
lock=flag;
if (flag)
_dpmi_lockregion(ourint9,4096);
else
_dpmi_unlockregion(ourint9,4096);
}
}
/********************** External interfaces ******************/
/* Disable ^ALT-DEL */
void noreboot()
{
lockint9(1);
oldint9=_dos_getvect(9);
_dos_setvect(9,ourint9);
}
/* Enable ^ALT-DEL */
void okreboot()
{
lockint9(0);
_dos_setvect(9,oldint9);
}
[LISTING FIVE]
/****************************************************************
* DISPLAY.C general purpose Microsoft C text display library *
* See also DISPLAY.H DIRPICK.C, and HISTO.C -- Al Williams *
****************************************************************/
#include <stdio.h>
#include <dos.h>
#include <string.h>
#include <stdarg.h>
#include "display.h"
/* global variable sets color of output */
int color=7;
/* primary colors for color monitor (see display.h) */
int colors[4]={ 0x1e, 0x70, 0x1c, 0x7e };
/* 1=mono monitor, 0=color, -1=unknown */
int mono=-1;
/* set video mode and detect mono monitor
this should always be called first */
void vidmode()
{
union REGS r;
if (mono<0)
{
r.h.ah=0xf;
int86(0x10,&r,&r);
mono=r.h.al==7;
}
r.x.ax=mono?7:3;
int86(0x10,&r,&r);
r.x.ax=0x500;
int86(0x10,&r,&r);
}
/* goto point x,y (from 0-79 and 0-24) */
void goxy(int x,int y)
{
union REGS r;
r.h.ah=2;
r.h.dh=y;
r.h.dl=x;
r.h.bh=0;
int86(0x10,&r,&r);
}
/* clear screen region */
void clears(int x0, int y0,int x1,int y1)
{
union REGS r;
r.x.ax=0x600;
r.h.bh=color;
r.h.ch=y0;
r.h.cl=x0;
r.h.dh=y1;
r.h.dl=x1;
int86(0x10,&r,&r);
goxy(0,0);
}
/* get x,y position */
void getxy(int *x,int *y)
{
union REGS r;
r.h.ah=3;
r.h.bh=0;
int86(0x10,&r,&r);
*x=r.h.dl;
*y=r.h.dh;
}
/* write count characters
-- handle \r, \n, backspace, and \a
updates the cursor if count==1 (w/o line wrap)
otherwise, the cursor doesn't move */
void writecc(int c,int count)
{
union REGS r;
/* PS/2 BIOS tries to print 0 characters! */
if (count<=0) return;
/* if bell character... */
if (c=='\a')
{
/* use function 0eH to do count bells */
while (count--)
{
r.x.ax=0xe00|'\a';
r.x.bx=0;
int86(0x10,&r,&r);
}
return;
}
/* if regular character (not \n or \r or bs) */
if (c!='\n'&&c!='\r'&&c!=8)
{
/* print regular character */
r.h.ah=9;
r.h.al=c;
r.h.bh=0;
r.h.bl=color;
r.x.cx=count;
int86(0x10,&r,&r);
/* if count isn't 1 return else do cursor update
NOTE: \n \r always update cursor */
if (count!=1) return;
}
/* get cursor position */
r.h.ah=3;
r.h.bh=0;
int86(0x10,&r,&r);
/* if \r, zero x coordinate
Note that 100 \r's is the same as 1 */
if (c=='\r')
r.h.dl=0;
/* if \n, increment y coordinate by count */
else if (c=='\n')
r.h.dh+=count;
/* if backspace back up by count or to start of line */
else if (c==8)
r.h.dl-=r.h.dl>count?count:r.h.dl;
else
/* bump x coordinate. Assume it won't wrap over */
r.h.dl++;
r.h.ah=2;
int86(0x10,&r,&r);
}
/* write a string using writec, a writecc macro
(see display.h) */
void writes(char *s)
{
while (*s) writec(*s++);
}
/* printf using writecc max length 99 */
int printfc(char *fmt,...)
{
int rc;
char outbuf[100];
va_list aptr;
va_start(aptr,fmt);
rc=vsprintf(outbuf,fmt,aptr);
writes(outbuf);
return rc;
}
/* prompt for single key @ coordinates x,y
use str as prompt, resp is valid keys, pcolor
is the color to use (0 for same color). Alpha characters
in resp should be upper case. If resp is "" then all
characters are valid. If resp is NULL then any alpha
character is valid.
returns:
-1 if ESC pressed
index of character if resp is valid
character if resp is NULL or ""
*/
int prompt_at(int x, int y, char *str,char *resp,int pcolor)
{
int ocolor,c;
char *index;
goxy(x,y);
ocolor=color;
if (pcolor) color=pcolor;
/* clear to end of line */
clreol();
writes(str);
while (1)
{
/* get key */
c=getch();
if (!c)
{
/* ignore extended keys */
getch();
continue;
}
/* if esc quit */
if (c==27) break;
/* shift upper */
c=toupper(c);
/* if resp in not null, check it */
if (resp&&(index=strchr(resp,c))) break;
/* if resp is null, check for alpha */
if (resp==NULL&&isalpha(c)) break;
/* if resp=="" then anything is OK */
if (resp&&!*resp) break;
}
color=ocolor;
goxy(x,y);
clreol();
curshide();
return c==27?-1:resp&&*resp?index-resp:c;
}
/* prompt for input @x,y. Prompt with promptstr valid is a string of valid
input characters (if NULL, all characters are OK., clr is the color
(0 for same), len is the input length, buf is the buffer (should be at
least len+1 long, and help is an optional help string (use NULL for the
default help). returns: -1 if ESC # of characters input otherwise
You can use the backspace key to edit entries */
int ask_at(int x, int y, char *promptstr,char *valid,
int clr,int len,char *buf,char *help)
{
int count=0,c,ocolor=color;
char *bp=buf;
/* clear buffer */
memset(buf,0,len+1);
/* set color, goto input line, and clear it */
if (clr) color=clr;
goxy(x,y);
clreol();
/* write prompt */
writes(promptstr);
/* main loop */
while (1)
{
/* get a character. Extended keys are <0 */
c=getch();
if (!c) c=-getch();
/* handle backspace */
if (c==8)
{
if (bp!=buf)
{
bp--;
writec(8);
writec(' ');
writec(8);
*bp='\0';
count--;
}
continue;
}
/* Escape or enter ends input */
if (c=='\r'||c==27)
{
/* restore color */
color=ocolor;
/* clear line */
goxy(x,y);
clreol();
curshide();
/* return */
return c==27?-1:count;
}
/* If F1 give help */
if (c==-59)
{
vidsave();
prompt(help?help:
" Use <ENTER> to accept, <ESC> to quit, <Backspace>"
" to correct.","",SOCOLOR);
vidrestore();
continue;
}
/* ignore other extended keys (c<0) or regular keys if
at input limit (count==len) */
if (count==len||c<0) continue;
/* if not valid character, ignore */
if (valid&&!strchr(valid,c)) continue;
/* echo input character */
writec(c);
/* store in buffer */
*bp++=c;
/* update count */
count++;
}
}
/* routines to save and restore the video context */
/* places to save things */
static char vbuf[4096];
static int save_xy,save_color;
/* save video */
void vidsave()
{
union REGS r;
save_color=color;
r.h.ah=3;
r.h.bh=0;
int86(0x10,&r,&r);
save_xy=r.x.dx;
memcpy((void *)vbuf,(void *)(mono?0xb0000:0xb8000),4096);
}
/* restore video */
void vidrestore()
{
union REGS r;
memcpy((void *)(mono?0xb0000:0xb8000),(void *)vbuf,4096);
color=save_color;
r.h.ah=2;
r.h.bh=0;
r.x.dx=save_xy;
int86(0x10,&r,&r);
}
[LISTING SIX]
/******************************************************************
* TIMING.C - simple non-rigorous benchmark for Phar Lap's *
* 286 | DOS Extender & Intel 386 CodeBuilder *
* Compile with: ICC timing.c graphics.lib (386 protected mode) *
* OR: *
* CL -AL -Lp -G2 -Ox timing.c graphp.obj llibpe.lib graphics.lib *
* (286 protected mode) *
* OR: *
* CL -AL -G2 -Ox timing.c graphics.lib *
* (real mode) *
******************************************************************/
#include <stdio.h>
#include <graph.h>
#include <time.h>
#define time_mark time_it(0)
#define time_done time_it(1)
main()
{
printf("Timing graphics operations\n");
time_mark;
gtest();
time_done;
printf("Timing file operations\n");
time_mark;
ftest();
time_done;
exit(0);
}
/* Function to mark times */
int time_it(int flag)
{
static clock_t sttime;
unsigned s;
if (!flag)
{
sttime=clock();
}
else
{
s=(clock()-sttime)/CLK_TCK;
printf("Elapsed time: %d seconds\n",s);
}
return 0;
}
/* Graphics test -- must have VGA */
int gtest()
{
int i,x,y;
_setvideomode(_MRES256COLOR);
for (i=1;i<11;i++)
{
_setcolor(i);
for (y=0;y<199;y++)
for (x=0;x<319;x++)
_setpixel(x,y);
}
_setvideomode(_DEFAULTMODE);
return 0;
}
/* File test -- assumes 320K free on current drive */
char filedata[64000];
int ftest()
{
FILE *tfile;
int i,j;
for (j=0;j<10;j++)
{
tfile=fopen("~~TIMING.~@~","w");
if (!tfile)
{
perror("TIMING");
exit(1);
}
for (i=0;i<5;i++)
fwrite(filedata,sizeof(filedata),1,tfile);
if (fclose(tfile))
{
perror("TIMING");
}
unlink("~~TIMING.~@~");
}
return 0;
}